﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int mian1()
{
	char arr1[] = { 'a', 'b', 'c', 'd' };
	char arr2[] = {"abcd"};


	return 0;
}

//int mian()
//{
//	int arr1[] = { 1,2,3,4 };
//	printf("%zd\n", sizeof(arr1));//计算的是整个数组的大小（字节）
//	printf("%zd\n", sizeof(arr1 + 0));
//	//计算的是整个数组的大小（字节）
//	return 0;
//}


//一维数组
int main2()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));


	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));


	return 0;
}
//int main()
//{//数组名没有单独放在sizeof内部，只能是数组首元素的地址
////&加数组名-->整个数组的地址
//	int a[3][4] = { 0 };
//	printf("%d\n", sizeof(a));//计算整个数组的大小，12 * 4 = 48
//	printf("%d\n", sizeof(a[0][0]));//4
//	printf("%d\n", sizeof(a[0]));//计算第一个一维数组的大小，4*4 = 16字节
//	printf("%d\n", sizeof(a[0] + 1));//a[0]:第一个一维数组的第一个元素的地址，即a[0][0]的地址
//	//a[0]+1:第一个一维数组的第二个元素的地址, 地址：4/8个字节
//	printf("%d\n", sizeof(*(a[0] + 1)));//第一个一维数组的第二个元素  4个字节
//	printf("%d\n", sizeof(a + 1));//int* [4]
//	//a:二维数组的数组名，首元素的地址即第一个一维数组的地址
//	//a[0]+1  -->  第二个一维数组的地址 4 / 8个字节
//	printf("%d\n", sizeof(*(a + 1)));//*(a+1)-->a[1] 单独放在sizeof内部，
//	//第二个一维数组的大小 4*4=16
//	printf("%d\n", sizeof(&a[0] + 1));//&a[0]-->第一个一维数组的地址
//	//&a[0]+1-->第二个一维数组的地址   4/8字节
//	printf("%d\n", sizeof(*(&a[0] + 1)));//第二个一维数组的大小 4*4=16
//	printf("%d\n", sizeof(*a));//首元素的地址，第一个一维数组的地址--->4*4 = 16
//	//*a -- *(a + 0) -- a[0]
//	printf("%d\n", sizeof(a[3]));//arr[3] 第四行的数组名 int[4]
//	//访问第四个一维数组,通过类型推断长度   4*4=16
//	//sizeof内部的表达式不会真的计算（访问），通过类型推断长度，不存在越界访问
//
//	return 0;
//}


//程序的结果是什么？
#include <stdio.h>
int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };//&a -- int(*)[5]
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));//a---首元素的地址  a+1---2的地址
	//ptr
	//2   5
	return 0;
}

//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结果是啥？
struct Test
{
	int Num;
	char* pcName;//环境
	short sDate;
	char cha[2];//2Byte
	short sBa[4];//4*2 = 8Byte
}*p = (struct Test*)0x100000;//结构体指针类型
int main()
{
	//只有指针+-整数，与类型有关
	printf("%p\n", p + 0x1);//p是结构体指针，+1跳过20个字节  20---->转成十六进制14
	//0x表示十六进制 ，0x1    0x100014
	printf("%p\n", (unsigned long)p + 0x1);//p是整数+1 -- 0x100001
	printf("%p\n", (unsigned int*)p + 0x1);//+1跳过4个字节的指针变量
	//0x100004
	return 0;
}

#include <stdio.h>
int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };//小括号 ,逗号表达式从左到右计算
	//但整个表达式的结果是最后一个表达式的结果
	//1, 3  5, 0  0, 0
	int* p;
	p = a[0];//存a[0]数组名，数组首元素的地址，即1的地址
	printf("%d", p[0]);// *(p+0)
	return 0;
}

//假设环境是x86环境，程序输出的结果是啥？
#include <stdio.h>
int main()
{
	int a[5][5];
	int(*p)[4];//数组指针
	p = a;//数组名表示数组首元素的地址，a的类型  int(*)[5] 
	//int(*p)[4] <--- int(*)[5] 
	//int(*p)[4]
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//-4  0xFF FF FF FC
	//p[4][2]==>*((*p+4)+2)
	// %p  %d
	// &p[4][2] - &a[4][2]--->-4     &a[4][2], &p[4][2] - &a[4][2]---->-4
	// -4的原码：10000000  00000000 00000000 00000100
	// -4的反码：11111111  11111111 11111111 11111011
	// -4的补码：11111111  11111111 11111111 11111100
	//  1111-->F  结果为0xFF FF FF FC
	//地址没有原码补码反码的概念,直接打印
	return 0;
}

#include <stdio.h>
int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);//&aa + 1--->跳过整个数组
	//(int*)-->转成指针类型
	int* ptr2 = (int*)(*(aa + 1));//aa-->数组首元素(第一个一维数组)的地址  
	//aa+1-->第二行的地址   *(aa + 1):6,7,8,9,10
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	//10  ,  5
	return 0;
}

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	//存的是 w , a , a 的地址
	char** pa = a;//a数组名 表示数组首元素的地址,存w地址的地址
	pa++;//存a的地址的地址
	printf("%s\n", *pa);//at
	return 0;
}

#include <stdio.h>
int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };//c-->数组首元素的地址
	char*** cpp = cp;
	//字符串打印，从起始位置开始到最后
	printf("%s\n", **++cpp);//POINT
	printf("%s\n", *-- * ++cpp + 3);//ENTER+3--->数组首元素的地址+3--->ER
	printf("%s\n", *cpp[-2] + 3);//*(*(cpp-2))+3---->FIRST+3--->首元素的地址+3--->ST
	printf("%s\n", cpp[-1][-1] + 1);//*(cpp-1)--->*(*(cpp-1)-1)---->*(*(cpp-1)-1)+1
	//EW
	return 0;
}